package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"encoding/json"
	"fmt"
	"xuefen_bank/crypt/curve"
	"xuefen_bank/crypt/recrypt"
	"xuefen_bank/utils"
)

func main() {
	// Alice Generate Alice key-pair
	aPriKey, aPubKey, _ := curve.GenerateKeys()
	aPriKeyPoint, _ := json.Marshal(&aPriKey)
	prikeyStr := utils.BytesToString(aPriKeyPoint)
	fmt.Println("json后的pri:   ", prikeyStr)
	aPubKeyPoint, _ := json.Marshal(aPubKey)
	pubkeyStr := utils.BytesToString(aPubKeyPoint)
	fmt.Println("json后的pub:   ", pubkeyStr)

	var aprivate *ecdsa.PrivateKey
	var apublic *ecdsa.PublicKey

	p256 := elliptic.P256()
	json.Unmarshal(utils.StrToByte(prikeyStr), &aprivate)

	json.Unmarshal(utils.StrToByte(pubkeyStr), &apublic)
	aprivate.PublicKey.Curve = p256
	apublic.Curve = p256
	marshal3, _ := json.Marshal(&aprivate)
	fmt.Println("反json后的pri:   ", string(marshal3))

	marshal4, _ := json.Marshal(&aprivate.PublicKey)
	fmt.Println("反json后的pub:   ", string(marshal4))

	// Bob Generate Bob key-pair
	bPriKey, bPubKey, _ := curve.GenerateKeys()
	bPriKeyPoint, _ := json.Marshal(&bPriKey)
	bprikeyStr := utils.BytesToString(bPriKeyPoint)
	fmt.Println("json后的pri:   ", prikeyStr)
	bPubKeyPoint, _ := json.Marshal(&bPubKey)
	bpubkeyStr := utils.BytesToString(bPubKeyPoint)
	fmt.Println("json后的pub:   ", bpubkeyStr)

	var bprivate *ecdsa.PrivateKey
	var bpublic ecdsa.PublicKey

	json.Unmarshal(utils.StrToByte(bprikeyStr), &bprivate)

	bprivate.PublicKey.Curve = p256
	bpublic.Curve = p256
	json.Unmarshal(utils.StrToByte(bpubkeyStr), &bpublic)
	bmarshal5, _ := json.Marshal(&bprivate)
	fmt.Println("反json后的pri:   ", string(bmarshal5))

	bmarshal6, _ := json.Marshal(&bpublic)
	fmt.Println("反json后的pub:   ", string(bmarshal6))

	// plain text
	m := "Hello, Proxy Re-Encryption,my22"
	fmt.Println("origin message:", m)
	// Alice encrypts to get cipherText and capsule
	cipherText, capsule, err := recrypt.Encrypt(m, apublic)
	if err != nil {
		fmt.Println(err)
	}
	/*capsuleAsBytes, err := crypt.EncodeCapsule(*capsule)
	if err != nil {
		fmt.Println("encode error:", err)
	}
	capsuleTest, err := crypt.DecodeCapsule(capsuleAsBytes)
	if err != nil {
		fmt.Println("decode error:", err)
	}
	fmt.Println("capsule before encode:", capsule)

	fmt.Println("capsule after decode:", capsuleTest)*/

	// Test recreate aes key
	/*	keyBytes, err := crypt.RecreateAESKeyByMyPriKey(capsule, aprivate)
		if err != nil {
			fmt.Println("Recreate key error:", err)
		}
		fmt.Println("recreate key:", hex.EncodeToString(keyBytes))*/
	fmt.Println("ciphereText:", cipherText)
	//会乱码
	//fmt.Println("ciphereText:", utils.BytesToString(cipherText))

	// Alice generates re-encryption key
	rk, pubX, err := recrypt.ReKeyGen(aprivate, &bpublic)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("rk:", rk)
	// Server executes re-encrypt
	newCapsule, err := recrypt.ReEncryption(rk, capsule)
	if err != nil {
		fmt.Println(err.Error())
	}
	cap, _ := json.Marshal(&newCapsule)
	capS := utils.BytesToString(cap)
	fmt.Println("json后的capS:   ", capS)
	var caps *recrypt.Capsule
	json.Unmarshal(utils.StrToByte(capS), &caps)

	caps.E.Curve = p256
	caps.V.Curve = p256
	var repub *ecdsa.PublicKey

	repubB, _ := json.Marshal(&pubX)
	repubS := utils.BytesToString(repubB)
	fmt.Println("json后的repubS:   ", repubS)

	json.Unmarshal(utils.StrToByte(repubS), &repub)
	repub.Curve = p256
	// Bob decrypts the cipherText
	plainText, err := recrypt.Decrypt(bprivate, caps, repub, cipherText)
	if err != nil {
		fmt.Println(err)
	}

	plainTextByMyPri, err := recrypt.DecryptOnMyPriKey(aprivate, capsule, cipherText)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("PlainText by my own private key:", string(plainTextByMyPri))
	// get plainText
	fmt.Println("plainText:", string(plainText))

	fileCapsule, err := recrypt.EncryptFile("crypt/a.txt", "crypt/a_encrypt.txt", aPubKey)
	if err != nil {
		fmt.Println("File Encrypt Error:", err)
	}
	fileNewCapsule, err := recrypt.ReEncryption(rk, fileCapsule)
	if err != nil {
		fmt.Println("ReEncryption Error:", err)
	}
	err = recrypt.DecryptFile("crypt/a_encrypt.txt", "crypt/a_decrypt.txt", bPriKey, fileNewCapsule, pubX)
	if err != nil {
		fmt.Println("Decrypt Error:", err)
	}
}
